#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <numeric>
using namespace std;

class union_set {
	vector<int> father;
public:
	union_set(int n)
	:father(n + 1, 0)
	{
		iota(father.begin(), father.end(), 0);
	}

	int find(int x)
	{
		return father[x] == x ? x : father[x] = find(father[x]);
	}

	int merge(int x, int y)
	{
		int fx = find(x);
		int fy = find(y);
		if(fx == fy){
			return 0;
		}else{
			father[fx] = fy;
			return 1;
		}
	}
};

int prim(const vector<vector<vector<int>>> &gh)
{
	int n = gh.size() - 1;
	vector<int> vis(n + 1, 0);
	auto cmp = [](const auto &a, const auto &b) { return a.second > b.second; };
	priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(cmp)> pq(cmp);
	pq.push({ 1, 0 });

	int ans = 0, cnt = 0;
	while (!pq.empty()) {
		auto e = pq.top();
		pq.pop();
		int u = e.first, w = e.second;
		if (!vis[u]) {
			vis[u] = 1;
			cnt++;
			ans += w;
			for (auto edge : gh[u]) {
				int v = edge[0], w = edge[1];
				if (!vis[v]) {
					pq.push({ v, w });
				}
			}
		}
	}

	return cnt == n ? ans : -1;
}

int klus(vector<vector<int>> &edges, int n)
{	
	union_set uset(n);
	auto cmp = [](auto &a, auto &b){ return a[2] < b[2]; };
	sort(edges.begin(), edges.end(), cmp);

	int ans = 0, cnt = 0;
	for(auto e : edges){
		if(uset.merge(e[0], e[1])){
			ans += e[2];
			if(++cnt == n - 1){
				return ans;
			}
		}
	}
	return -1;
}

int main()
{
	int n = 0, m = 0;
	cin >> n >> m;
	vector<vector<vector<int>>> gh(n + 1);
	vector<vector<int>> edges;
	for (int i = 0; i < m; i++) {
		int u, v, w;
		cin >> u >> v >> w;
		gh[u].push_back({ v, w });
		gh[v].push_back({ u, w });

		edges.push_back({u, v, w});
	}

	//int ans = prim(gh);
	int ans = klus(edges, n);
	if (ans < 0) {
		cout << "orz" << endl;
	} else {
		cout << ans << endl;
	}

	return 0;
}